//
//  DemoString.swift
//  swiftDemo
//
//  Created by JIENING ZHANG on 2020/1/9.
//  Copyright © 2020 lovivid. All rights reserved.
//

import Foundation
import UIKit

class DemoString: NSObject {
    
    class func stringFromToArray() {
        
        let monthArr:[String] = [
                           "January",
                           "February",
                           "March",
                           "April",
                           "May",
                           "June",
                           "July",
                           "August",
                           "September",
                           "October",
                           "November",
                           "December",
                           ];
        
        // 数组 --'分隔符'--> 字符串
        let monthsStr = monthArr.joined(separator: "|");
        
        print("arr2String: arr\(monthArr) --> string\(monthsStr)");
        
        // 字符串 --'分隔符'--> 数组
        let weekdayStr = "Mon-Tue-Wed-Thu-Fri-Sat-Sun";
        
        let weekdayArr:[String] = weekdayStr.components(separatedBy: "-")
        
         print("String2arr: string\(weekdayArr) -->  arr\(weekdayStr)");
/*
输出:

arr2String: arr["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] --> stringJanuary|February|March|April|May|June|July|August|September|October|November|December
String2arr: string["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] -->  arrMon-Tue-Wed-Thu-Fri-Sat-Sun
*/
    }
    
    class func stringJoin() {
        
        let part1 = "七律·长征"
        let part2 = "毛泽东"
        let part3 = "1935年10月"
        let part4 = "红军不怕远征难，万水千山只等闲。"
        let part5 = "五岭逶迤腾细浪，乌蒙磅礴走泥丸。"
        let part6 = "金沙水拍云崖暖，大渡桥横铁索寒。"
        let part7 = "更喜岷山千里雪，三军过后尽开颜。"
        
        var all:String = "\(part1)\n\(part2)\n\(part3)\n\(part4)\n\(part5)\n\(part6)\n\(part7)"
        print ("() joint : \(all)");
        
        all = part1 + part2 + part3 + part4 + part5 + part6 + part7;
        print ("plus joint : \(all)");
        
        all = String.init(format: "%@\n%@\n%@\n%@\n%@\n%@\n%@\n", arguments:[part1, part2, part3, part4, part5, part6, part7]);
        print ("format joint : \(all)");
        
        all = part1;
        all = all.appending(part2);
        all = all.appending(part3);
        all = all.appending(part4);
        all = all.appending(part5);
        all = all.appending(part6);
        all = all.appending(part7);
        
        print ("appending joint : \(all)");
        
/*
() joint : 七律·长征
毛泽东
1935年10月
红军不怕远征难，万水千山只等闲。
五岭逶迤腾细浪，乌蒙磅礴走泥丸。
金沙水拍云崖暖，大渡桥横铁索寒。
更喜岷山千里雪，三军过后尽开颜。
plus joint : 七律·长征毛泽东1935年10月红军不怕远征难，万水千山只等闲。五岭逶迤腾细浪，乌蒙磅礴走泥丸。金沙水拍云崖暖，大渡桥横铁索寒。更喜岷山千里雪，三军过后尽开颜。
format joint : 七律·长征
毛泽东
1935年10月
红军不怕远征难，万水千山只等闲。
五岭逶迤腾细浪，乌蒙磅礴走泥丸。
金沙水拍云崖暖，大渡桥横铁索寒。
更喜岷山千里雪，三军过后尽开颜。

appending joint : 七律·长征毛泽东1935年10月红军不怕远征难，万水千山只等闲。五岭逶迤腾细浪，乌蒙磅礴走泥丸。金沙水拍云崖暖，大渡桥横铁索寒。更喜岷山千里雪，三军过后尽开颜。
*/
    }
    
    class func subStringSearch() {
        
        let ostr = "浔阳江头夜送客，枫叶荻花秋瑟瑟。主人下马客在船，举酒欲饮无管弦。醉不成欢惨将别，别时茫茫江浸月。忽闻水上琵琶声，主人忘归客不发。寻声暗问弹者谁，琵琶声停欲语迟。移船相近邀相见，添酒回灯重开宴。千呼万唤始出来，犹抱琵琶半遮面。转轴拨弦三两声，未成曲调先有情。弦弦掩抑声声思，似诉平生不得志。低眉信手续续弹，说尽心中无限事。轻拢慢捻抹复挑，初为《霓裳》后《六幺》。大弦嘈嘈如急雨，小弦切切如私语。嘈嘈切切错杂弹，大珠小珠落玉盘。间关莺语花底滑，幽咽泉流冰下难。冰泉冷涩弦凝绝，凝绝不通声暂歇。别有幽愁暗恨生，此时无声胜有声。银瓶乍破水浆迸，铁骑突出刀枪鸣。曲终收拨当心画，四弦一声如裂帛。东船西舫悄无言，唯见江心秋月白。沉吟放拨插弦中，整顿衣裳起敛容。自言本是京城女，家在虾蟆陵下住。十三学得琵琶成，名属教坊第一部。曲罢曾教善才服，妆成每被秋娘妒。五陵年少争缠头，一曲红绡不知数。钿头银篦击节碎，血色罗裙翻酒污。今年欢笑复明年，秋月春风等闲度。弟走从军阿姨死，暮去朝来颜色故。门前冷落鞍马稀，老大嫁作商人妇。商人重利轻别离，前月浮梁买茶去。去来江口守空船，绕船月明江水寒。夜深忽梦少年事，梦啼妆泪红阑干。我闻琵琶已叹息，又闻此语重唧唧。同是天涯沦落人，相逢何必曾相识！我从去年辞帝京，谪居卧病浔阳城。浔阳地僻无音乐，终岁不闻丝竹声。住近湓江地低湿，黄芦苦竹绕宅生。其间旦暮闻何物？杜鹃啼血猿哀鸣。春江花朝秋月夜，往往取酒还独倾。岂无山歌与村笛？呕哑嘲哳难为听。今夜闻君琵琶语，如听仙乐耳暂明。莫辞更坐弹一曲，为君翻作《琵琶行》。感我此言良久立，却坐促弦弦转急。凄凄不似向前声，满座重闻皆掩泣。座中泣下谁最多？江州司马青衫湿。";
        
        // 从头到尾 查找第一处
        let rangeHead = ostr.range(of: "琵琶");
        if rangeHead != nil {
            let fstr = ostr.prefix(upTo: rangeHead!.lowerBound);
            print("第一处\"琵琶\"之前 : "+fstr)
        }
        
        // 从末尾向开头 查找第一处
        let rangeTail = ostr.range(of:"琵琶", options:.backwards, range: nil, locale: nil)
        if rangeTail != nil {
            let fstr = ostr.suffix(from:rangeTail!.upperBound);
            print("最后一处\"琵琶\"之后 : "+fstr)
        }
        
        // 替换所有命中的 琵琶 为 PiPa
        var rpstr = ostr.replacingOccurrences(of: "琵琶", with: "PiPa")
        print("替换所有 琵琶 为 PiPa : "+rpstr)
        
        // 替换某个range 为 PiPa
        if rangeHead != nil {
            rpstr = ostr.replacingCharacters(in:rangeHead!, with: "PiPa")
        }
        print("替换第一处 琵琶 为 PiPa : "+rpstr)
/*
输出:
         
第一处"琵琶"之前 : 浔阳江头夜送客，枫叶荻花秋瑟瑟。主人下马客在船，举酒欲饮无管弦。醉不成欢惨将别，别时茫茫江浸月。忽闻水上
最后一处"琵琶"之后 : 行》。感我此言良久立，却坐促弦弦转急。凄凄不似向前声，满座重闻皆掩泣。座中泣下谁最多？江州司马青衫湿。
替换所有 琵琶 为 PiPa : 浔阳江头夜送客，枫叶荻花秋瑟瑟。主人下马客在船，举酒欲饮无管弦。醉不成欢惨将别，别时茫茫江浸月。忽闻水上PiPa声，主人忘归客不发。寻声暗问弹者谁，PiPa声停欲语迟。移船相近邀相见，添酒回灯重开宴。千呼万唤始出来，犹抱PiPa半遮面。转轴拨弦三两声，未成曲调先有情。弦弦掩抑声声思，似诉平生不得志。低眉信手续续弹，说尽心中无限事。轻拢慢捻抹复挑，初为《霓裳》后《六幺》。大弦嘈嘈如急雨，小弦切切如私语。嘈嘈切切错杂弹，大珠小珠落玉盘。间关莺语花底滑，幽咽泉流冰下难。冰泉冷涩弦凝绝，凝绝不通声暂歇。别有幽愁暗恨生，此时无声胜有声。银瓶乍破水浆迸，铁骑突出刀枪鸣。曲终收拨当心画，四弦一声如裂帛。东船西舫悄无言，唯见江心秋月白。沉吟放拨插弦中，整顿衣裳起敛容。自言本是京城女，家在虾蟆陵下住。十三学得PiPa成，名属教坊第一部。曲罢曾教善才服，妆成每被秋娘妒。五陵年少争缠头，一曲红绡不知数。钿头银篦击节碎，血色罗裙翻酒污。今年欢笑复明年，秋月春风等闲度。弟走从军阿姨死，暮去朝来颜色故。门前冷落鞍马稀，老大嫁作商人妇。商人重利轻别离，前月浮梁买茶去。去来江口守空船，绕船月明江水寒。夜深忽梦少年事，梦啼妆泪红阑干。我闻PiPa已叹息，又闻此语重唧唧。同是天涯沦落人，相逢何必曾相识！我从去年辞帝京，谪居卧病浔阳城。浔阳地僻无音乐，终岁不闻丝竹声。住近湓江地低湿，黄芦苦竹绕宅生。其间旦暮闻何物？杜鹃啼血猿哀鸣。春江花朝秋月夜，往往取酒还独倾。岂无山歌与村笛？呕哑嘲哳难为听。今夜闻君PiPa语，如听仙乐耳暂明。莫辞更坐弹一曲，为君翻作《PiPa行》。感我此言良久立，却坐促弦弦转急。凄凄不似向前声，满座重闻皆掩泣。座中泣下谁最多？江州司马青衫湿。
替换第一处 琵琶 为 PiPa : 浔阳江头夜送客，枫叶荻花秋瑟瑟。主人下马客在船，举酒欲饮无管弦。醉不成欢惨将别，别时茫茫江浸月。忽闻水上PiPa声，主人忘归客不发。寻声暗问弹者谁，琵琶声停欲语迟。移船相近邀相见，添酒回灯重开宴。千呼万唤始出来，犹抱琵琶半遮面。转轴拨弦三两声，未成曲调先有情。弦弦掩抑声声思，似诉平生不得志。低眉信手续续弹，说尽心中无限事。轻拢慢捻抹复挑，初为《霓裳》后《六幺》。大弦嘈嘈如急雨，小弦切切如私语。嘈嘈切切错杂弹，大珠小珠落玉盘。间关莺语花底滑，幽咽泉流冰下难。冰泉冷涩弦凝绝，凝绝不通声暂歇。别有幽愁暗恨生，此时无声胜有声。银瓶乍破水浆迸，铁骑突出刀枪鸣。曲终收拨当心画，四弦一声如裂帛。东船西舫悄无言，唯见江心秋月白。沉吟放拨插弦中，整顿衣裳起敛容。自言本是京城女，家在虾蟆陵下住。十三学得琵琶成，名属教坊第一部。曲罢曾教善才服，妆成每被秋娘妒。五陵年少争缠头，一曲红绡不知数。钿头银篦击节碎，血色罗裙翻酒污。今年欢笑复明年，秋月春风等闲度。弟走从军阿姨死，暮去朝来颜色故。门前冷落鞍马稀，老大嫁作商人妇。商人重利轻别离，前月浮梁买茶去。去来江口守空船，绕船月明江水寒。夜深忽梦少年事，梦啼妆泪红阑干。我闻琵琶已叹息，又闻此语重唧唧。同是天涯沦落人，相逢何必曾相识！我从去年辞帝京，谪居卧病浔阳城。浔阳地僻无音乐，终岁不闻丝竹声。住近湓江地低湿，黄芦苦竹绕宅生。其间旦暮闻何物？杜鹃啼血猿哀鸣。春江花朝秋月夜，往往取酒还独倾。岂无山歌与村笛？呕哑嘲哳难为听。今夜闻君琵琶语，如听仙乐耳暂明。莫辞更坐弹一曲，为君翻作《琵琶行》。感我此言良久立，却坐促弦弦转急。凄凄不似向前声，满座重闻皆掩泣。座中泣下谁最多？江州司马青衫湿。
*/
    }
    
    class func stringFormat() {
        
        // =========== 类型格式符 =============
        
        // %@       Objective-C object, printed as the string returned by descriptionWithLocale: if available, or description otherwise.
        //          输出OC对象，如果OC对象实现了descriptionWithLocale:方法，输出这个方法的返回值，如果没有，输出 description 方法返回值
        // %d,%D    Signed 32-bit integer (int).
        //          10进制输出32位整形
        
        // %u,%U    Unsigned 32-bit integer (unsigned int).
        //          10进制输出32位无符号整形
        // %x       Unsigned 32-bit integer (unsigned int), printed in hexadecimal using the digits 0–9 and lowercase a–f.
        //          16进制输出32位无符号整形，a到f用小写字母
        // %X       Unsigned 32-bit integer (unsigned int), printed in hexadecimal using the digits 0–9 and uppercase A–F.
        //          16进制输出32位无符号整形，A到F用大写字母
        // %o, %O   Unsigned 32-bit integer (unsigned int), printed in octal.
        //          8进制输出32位无符号整形
        
        // %f       64-bit floating-point number (double).
        //          输出64位双精浮点数
        // %F       64-bit floating-point number (double), printed in decimal notation.
        //          输出64位双精浮点数, 10 进制
        // %e       64-bit floating-point number (double), printed in scientific notation using a lowercase e to introduce the exponent.
        //          输出64位双精浮点数，使用科学计数法，其中e使用小写字母
        // %E       64-bit floating-point number (double), printed in scientific notation using a uppercase E to introduce the exponent.
        //          输出64位双精浮点数，使用科学计数法，其中E使用大写字母
        // %g       64-bit floating-point number (double), printed in the style of %e if the exponent is less than –4 or greater than or equal to the precision, in the style of %f otherwise.
        //          输出64位双精浮点数，如果指数e部分的数比-4小，按照 %e 输出，否则按照 %f输出
        // %G       64-bit floating-point number (double), printed in the style of %E if the exponent is less than –4 or greater than or equal to the precision, in the style of %f otherwise.
        //          输出64位双精浮点数，如果指数e部分的数比-4小，按照 %E 输出，否则按照 %f输出
        // %a       64-bit floating-point number (double), printed in scientific notation with a leading 0x and one hexadecimal digit before the decimal point using a lowercase p to introduce the exponent.
        //          输出64位双精浮点数，使用科学计数法，在小数点前使用一位16进制数，0x为先导，使用小写p表示指数部分
        // %A       64-bit floating-point number (double), printed in scientific notation with a leading 0X and one hexadecimal digit before the decimal point using a uppercase P to introduce the exponent.
        //          输出64位双精浮点数，使用科学计数法，在小数点前使用一位16进制数，0X为先导，使用大写P表示指数部分

        

        
        // %c       8-bit unsigned character (unsigned char).
        //          输出字符，适用类型为无符号char
        // %C       16-bit UTF-16 code unit (unichar).
        //          输出UTF-16字符，适用类型为unichar
        
        // %s       Null-terminated array of 8-bit unsigned characters. Because the %s specifier causes the characters to be interpreted in the system default encoding, the results can be variable, especially with right-to-left languages. For example, with RTL, %s inserts direction markers when the characters are not strongly directional. For this reason, it’s best to avoid %s and specify encodings explicitly.
        //          输出以Null结尾的8比特无符号字符为单元的字符数组，使用该格式符，将根据系统默认编码解释字符，所以输出结果不定，特别是从右到左书写的语言。因此最好不要使用%s
        // %S       Null-terminated array of 16-bit UTF-16 code units.
        //          输出以Null结尾的16比特UTF-16字符为单元的字符数组
        
        // %p       Void pointer (void *), printed in hexadecimal with the digits 0–9 and lowercase a–f, with a leading 0x.
        //          （这是小写p）打印void指针地址，使用0x先导，16进制输出，a到f使用小写字母
        
        
        // =========== 长度格式符 =============
        
        // h        Length modifier specifying that a following d, o, u, x, or X conversion specifier applies to a short or unsigned short argument.
        //          h 后面可以跟 d, o, u, x, X，表示在这些特定类型接收一个 shor 或是 unsigned short 参数
        // hh       Length modifier specifying that a following d, o, u, x, or X conversion specifier applies to a signed char or unsigned char argument.
        //          hh 后面可以跟 d, o, u, x, X，表示在这些特定类型接收一个 char 或是 unsigned char 参数
        // l        Length modifier specifying that a following d, o, u, x, or X conversion specifier applies to a long or unsigned long argument.
        //          l 后面可以跟 d, o, u, x, X，表示在这些特定类型接收一个 long 或是 unsigned long 参数
        // ll,q     Length modifiers specifying that a following d, o, u, x, or X conversion specifier applies to a long long or unsigned long long argument.
        //          ll 后面可以跟 d, o, u, x, X，表示在这些特定类型接收一个 long long 或是 unsigned long long参数
        // L        Length modifier specifying that a following a, A, e, E, f, F, g, or G conversion specifier applies to a long double argument.
        //          L 后面可以跟 a, A, e, E, f, F, g, G 表示在这些特定类型接收一个 long double 参数
        // z        Length modifier specifying that a following d, o, u, x, or X conversion specifier applies to a size_t.
        //          z 后面可以跟 d, o, u, x, X 表示在这些特定类型接收一个 size_t 参数
        // t        Length modifier specifying that a following d, o, u, x, or X conversion specifier applies to a ptrdiff_t.
        //          z 后面可以跟 d, o, u, x, X 表示在这些特定类型接收一个 ptrdiff_t 参数
        
        
        /*
         ptrdiff_t是C/C++标准库中定义的一个与机器相关的数据类型。
         ptrdiff_t类型变量通常用来保存两个指针减法操作的结果。
         ptrdiff_t定义在stddef.h（cstddef）这个文件内。ptrdiff_t通常被定义为long int类型。
         ptrdiff_t定义在C99标准中。
         标准库类型(library type)ptrdiff_t 与 size_t 类型一样,ptrdiff_t 也是一种与机器相关的类型,在 cstddef 头文件中定义。
         size_t 是unsigned 类型,而 ptrdiff_t 则是 signed 整型 [1]  。
         这两种类型的差别体现了它们各自的用途：size_t 类型用于指明数组长度,它必须是一个正数;ptrdiff_t 类型则应保证足以存放同一数组中两个指针之间的差距,它有可能是负数 [1]  。
         */
        
        // NSInteger CFIndex    使用 %ld or %lx 格式化输出
        // NSUInteger           使用 %lu or %lx 格式化输出
        // CGFloat              使用 %f or %g 格式化输出
        
        
        
        let numInt32:Int = -1024;
        
        let numUInt32:UInt = 1024;
        

        let numF64:Double = 31415.92654;
        
        let numCharacter:Character = "A";
        //let unicodeValue = UnicodeScalar("A");
        
        let numInt16:Int16 = 0xab;

        let numCGFloat:Float = 2.71828182846;
        
        // swift5
        if numCharacter.isASCII {
            print(String.init(format:"输出字符，适用类型为无符号char %%c:%c", arguments:[numCharacter.asciiValue!]));
        }
        
        print(String.init(format:"输出UTF-16字符，适用类型为unichar %%C:%C", arguments:[numInt16]));
        print(String.init(format:"10进制输出32位整形 %%d:%d %%D:%D", arguments:[numInt32, numInt32]));
        print(String.init(format:"10进制输出32位无符号整形 %%u:%u %%U:%U", arguments:[numUInt32, numUInt32]));
        print(String.init(format:"16进制输出32位无符号整形 %%x:%x %%X:%X", arguments:[numUInt32, numUInt32]));
        print(String.init(format:"8进制输出32位无符号整形 %%o:%o %%O:%O", arguments:[numUInt32, numUInt32]));
        
        print(String.init(format:"输出64位双精浮点数 %%f:%f %%F:%F %%e:%e %%E:%E %%g:%g %%G:%G %%a:%a %%A:%A", arguments:[numF64, numF64, numF64, numF64, numF64, numF64]));
        
        print(String.init(format:"输出64位双精浮点数, 3位小数 %%.3f:%.3f", arguments:[numCGFloat]));
        
/*
输出：

输出字符，适用类型为无符号char %c:A
输出UTF-16字符，适用类型为unichar %C:«
10进制输出32位整形 %d:-1024 %D:4294966272
10进制输出32位无符号整形 %u:1024 %U:1024
16进制输出32位无符号整形 %x:400 %X:400
8进制输出32位无符号整形 %o:2000 %O:2000
输出64位双精浮点数 %f:31415.926540 %F:31415.926540 %e:3.141593e+04 %E:3.141593E+04 %g:31415.9 %G:31415.9 %a:0x0p+0 %A:0X0P+0
输出64位双精浮点数, 3位小数 %.3f:2.718
*/
    }
    
    class func stringFromToDate() {
        
        /*
         // https://www.jianshu.com/p/a2c7e1a85192
         // http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_Patterns
         [dateStringFormatter setDateFormat:@"y"]; // 2017
         [dateStringFormatter setDateFormat:@"yy"]; // 17
         [dateStringFormatter setDateFormat:@"yyy"]; // 2017
         [dateStringFormatter setDateFormat:@"yyyy"]; // 2017
         
         [dateStringFormatter setDateFormat:@"M"]; // 8
         [dateStringFormatter setDateFormat:@"MM"]; // 08
         [dateStringFormatter setDateFormat:@"MMM"]; // 8月
         [dateStringFormatter setDateFormat:@"MMMM"]; // 八月
         
         [dateStringFormatter setDateFormat:@"d"]; // 3
         [dateStringFormatter setDateFormat:@"dd"]; // 03
         [dateStringFormatter setDateFormat:@"D"]; // 215,一年中的第几天
         
         [dateStringFormatter setDateFormat:@"h"]; // 4
         [dateStringFormatter setDateFormat:@"hh"]; // 04
         [dateStringFormatter setDateFormat:@"H"]; // 16 24小时制
         [dateStringFormatter setDateFormat:@"HH"]; // 16
         
         [dateStringFormatter setDateFormat:@"m"]; // 28
         [dateStringFormatter setDateFormat:@"mm"]; // 28
         [dateStringFormatter setDateFormat:@"s"]; // 57
         [dateStringFormatter setDateFormat:@"ss"]; // 04
         
         [dateStringFormatter setDateFormat:@"E"]; // 周四
         [dateStringFormatter setDateFormat:@"EEEE"]; // 星期四
         [dateStringFormatter setDateFormat:@"EEEEE"]; // 四
         [dateStringFormatter setDateFormat:@"e"]; // 5 (显示的是一周的第几天（weekday），1为周日。)
         [dateStringFormatter setDateFormat:@"ee"]; // 05
         [dateStringFormatter setDateFormat:@"eee"]; // 周四
         [dateStringFormatter setDateFormat:@"eeee"]; // 星期四
         [dateStringFormatter setDateFormat:@"eeeee"]; // 四
         
         [dateStringFormatter setDateFormat:@"z"]; // GMT+8
         [dateStringFormatter setDateFormat:@"zzzz"]; // 中国标准时间
         
         [dateStringFormatter setDateFormat:@"ah"]; // 下午5
         [dateStringFormatter setDateFormat:@"aH"]; // 下午17
         [dateStringFormatter setDateFormat:@"am"]; // 下午53
         [dateStringFormatter setDateFormat:@"as"]; // 下午52
         
         [dateStringFormatter setDateFormat:@"ww"]; // Week of Year
         [dateStringFormatter setDateFormat:@"W"]; // Week of Month
         [dateStringFormatter setDateFormat:@"qq"]; // 第几季度，比如一季度日期显示：01
         [dateStringFormatter setDateFormat:@"qqq"]; // 第几季度，比如一季度日期显示：Q1
         */
        let df1 = DateFormatter()
        df1.dateFormat = "yyyy-MM-dd HH:mm:ss" // 年-月-日 时:分:秒
        
        let dateStr1 = "2019-05-05 23:32:59"
        let date1 = df1.date(from: dateStr1)
        if date1 != nil {
            print("string2Date 年-月-日 时:分:秒 : string \(dateStr1) --> date \(date1!)")
        }
        
        let df2 = DateFormatter()
        df2.dateFormat = "yyyy|qq" // 年|季度
        
        let dateStr2 = "2019|02"
        let date2 = df2.date(from: dateStr2)
        if date2 != nil {
            print("string2Date 年|季度          : string \(dateStr2) --> date \(date2!)")
        }
        
        let df3 = DateFormatter()
        df3.dateFormat = "yyyy/ww" // 年/周

        let dateStr3 = "2019/10"
        let date3 = df3.date(from: dateStr3)
        if date3 != nil {
            print("string2Date 年/周            : string \(dateStr3) --> date \(date3!)")
        }
        
        let dateNow = Date()
        print("date2String 年-月-日 时:分:秒 : date \(dateNow) --df1 \(df1.dateFormat!)--> string \(df1.string(from:dateNow))")
        print("date2String 年|季度          : date \(dateNow) --df2 \(df2.dateFormat!)--> string \(df2.string(from:dateNow))")
        print("date2String 年/周            : date \(dateNow) --df3 \(df3.dateFormat!)--> string \(df3.string(from:dateNow))")
        
/*
输出：

 string2Date 年-月-日 时:分:秒 : string 2019-05-05 23:32:59 --> date 2019-05-05 15:32:59 +0000
 string2Date 年|季度          : string 2019|02 --> date 2019-03-31 16:00:00 +0000
 string2Date 年/周            : string 2019/10 --> date 2019-03-02 16:00:00 +0000
 date2String 年-月-日 时:分:秒 : date 2020-01-11 04:07:17 +0000 --df1 yyyy-MM-dd HH:mm:ss--> string 2020-01-11 12:07:17
 date2String 年|季度          : date 2020-01-11 04:07:17 +0000 --df2 yyyy|qq--> string 2020|01
 date2String 年/周            : date 2020-01-11 04:07:17 +0000 --df3 yyyy/ww--> string 2020/02
*/
        
    }
    
    // 使用 NSPredicate 判别 ostr 是否符合 pattern
    class func regexPredicate(ostr:String, pattern:String) {
        
        //Predicate：断言，谓语，术语的意思。
        //表示一个可以用来过滤对象集合的条件。通常，我们可以从 NSComparisonPredicate, NSCompoundPredicate, 和 NSExpression的实例直接创建predicates，但是，
        //我们也可以从格式化的string来创建predicates，这个格式化的string可以被NSPredicate的类方法解析。
        
        let predicateObj = NSPredicate(format:"SELF MATCHES %@", pattern)
        
        // 和 pattern 全等才算 match，包含但不全等不算
        if predicateObj.evaluate(with: ostr) {
            print("NSPredicate, \(ostr) match idPattern : \(pattern)")
        } else {
            print("NSPredicate, \(ostr) not match idPattern : \(pattern)")
        }
    }
    
    // 使用 String 的方法 range(of: options: range: locale) 做正则查询（第一处）
    // 使用 String 的方法 replacingOccurrences(of: with: options: range) 做正则替换（所有匹配都替换）
    class func regexSearch2Replace(originStr:String, replaceStr:String, pattern:String) {
        
        // 正则查找，返回从头到尾第一个匹配的位置
        let rangeHead = originStr.range(of:     pattern,
                                     options:   .regularExpression,
                                     range:     originStr.startIndex..<originStr.endIndex,
                                     locale:    Locale.current)
        
        if rangeHead == nil {
            print("regexSearch2Replace, find pattern \(pattern) --> fail to find")
        } else {
            
            //let newStr = String(str[..<index]) // = str.substring(to: index) In Swift 3
            //let newStr = String(str[index...]) // = str.substring(from: index) In Swif 3
            //let newStr = String(str[range]) // = str.substring(with: range) In Swift 3
            let fstr = originStr[rangeHead!]
            print("regexSearch2Replace, find pattern \(pattern) --> find \(fstr)")
            
            // 正则替换（所有匹配都替换）
            let strReplaced = originStr.replacingOccurrences(of: pattern,
                                           with: replaceStr,
                                           options: .regularExpression,
                                           range: originStr.startIndex ..< originStr.endIndex)
            
            print("regexSearch2Replace, \(pattern) --> \(replaceStr) :\n \(strReplaced)")
        }
        

        
        // 正则替换，替换所有匹配的
        //NSString *rpstr = [ostr stringByReplacingOccurrencesOfString:pattern withString:@"===email-replaced===" options:NSRegularExpressionSearch range:NSMakeRange(0, ostr.length)];
        //NSLog(@"rpstr : %@", rpstr);
    }
    
    class func regexSearchByRegularExpression(originStr:String, replaceStr:String, pattern:String) {
        
        // NSRegularExpression
        let regex = try? NSRegularExpression(pattern: pattern, options:[NSRegularExpression.Options.caseInsensitive])
        if regex != nil {
            print("regexSearchByRegularExpression, pattern format done : \(pattern)")
        } else {
            print("regexSearchByRegularExpression, pattern format error : \(pattern)")
            return
        }
        
        
        let resultNum = regex!.numberOfMatches(in: originStr, options: NSRegularExpression.MatchingOptions(rawValue: 0) , range: NSMakeRange(0, originStr.count))
        if resultNum == 0 {
            print("    no match : \(pattern)")
            return
        }
        print("    match count:\(resultNum)")
        
        //返回第一个符合约定的字段
        let firstMatch = regex!.firstMatch(in: originStr, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, originStr.count))
        print("    firstMatch:\(firstMatch!)")
        
        // 返回一个存有所有符合约定的字段的NSArray
        let allMatch = regex!.matches(in: originStr, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, originStr.count))
        print("    allMatch.count:\(allMatch.count)")
        for (index, match) in allMatch.enumerated() {
            print("        forloop: \(index) \(match)")
        }
        
        //枚举每个符合约定的字段，通过block对其进行操作
        regex!.enumerateMatches(in: originStr, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, originStr.count)) { (match:NSTextCheckingResult?, flag:NSRegularExpression.MatchingFlags, stop:UnsafeMutablePointer<ObjCBool>) in
             print("        enumerate block: \(flag) \(match!)")
        }
        
        // 返回 全部替换 后的字符串
        let rpstr = regex!.stringByReplacingMatches(in: originStr, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, originStr.count), withTemplate: replaceStr)
        print("    stringByReplacingMatches --> rpstr : \(rpstr)")

        // 构建 NSMutableString对象，全部替换后的结果，就在 新建的 NSMutableString对象 中
        let mostr = NSMutableString.init(string: originStr)
        let rpCount = regex!.replaceMatches(in: mostr, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, originStr.count), withTemplate: replaceStr)
        print("    replaceMatches(NSMutableString) --> rpCount : \(rpCount)")
        print("    replaceMatches(NSMutableString) --> mostr : \(mostr)")
    }
    
    class func regexSearch() {
        
        /*
         
         ^[A-Za-z]+$　　          //匹配由26个英文字母组成的字符串
         ^[A-Za-z0-9]+$　　       //匹配由数字和26个英文字母组成的字符串
         ^\w+$　　                //匹配由数字、26个英文字母或者下划线组成的字符串 相当于“[a-zA-Z0-9\u4E00-\u9FFF_]”
         [ ]                     //表示内容的范围； eg:“[a-zA-Z]”表示任一字母；“[ab]”表示“a”或“b”
         {}                      //表示数量的范围； eg:“{2}”表示2个；“{2,5}”表示2个到5个；“{3,}”表示至少3个；
         |                       //表示 或；eg:“a|b”表示“a”或“b”
         \num                    //num为一个整数，表示前面的表达式复制num次；eg:“(ab)\3”表示“ababab”
         \b                      //表示单词的开始或结束；
         \d                      //表示数字，相当于“[0-9]”;
         \s                      //表示任意空白符；
         
         反义字符
         \W                     //表示不是字符数字下划线或者汉字的字符；
         \S                     //表示任意不是空白符的字符；
         \D                     //表示不是数字的字符；
         \B                     //表示不是单词开头或结束的位置；
         [^x]                   //表示除“x”外的任意字符；
         [^abc]                 //表示除“a”“b”“c”外的任意字符；
        
         
         \\d                // 代表数字
         {2}                // 代表有两个
         {2,4}              // 代表有2到4个
         ?                  // 代表0或1个
         +                  // 代表至少1个
         *                  // 代表0个或多个
         ^                  // 代表以...开头
         $                  // 代表以...结束
         .                  // 代表除换行符以外的任意字符
         [\u4e00-\u9fa5]    // 匹配中文字符
         
         */
        
        let ostr = "百科熊猫词条  https://baike.baidu.com/item/%E5%A4%A7%E7%86%8A%E7%8C%AB/34935?fromtitle=%E7%86%8A%E7%8C%AB&fromid=162918&fr=aladdin  panda@163.com 大熊猫（学名：Ailuropoda melanoleuca）：属于食肉目、熊科、大熊猫亚科和大熊猫属唯一的哺乳动物，头躯长1.2-1.8米，尾长10-12厘米。体重80-120千克，最重可达180千克，体色为黑白两色，它有着圆圆的脸颊，大大的黑眼圈，胖嘟嘟的身体，标志性的内八字的行走方式，也有解剖刀般锋利的爪子。是世界上最可爱的动物之一。  panda@gmail.com  com.panda@gmail (010)88886666 ，或 022-22334455，或 02912345678 511122198812068932 41112219881206893X 18660000062 17000000026 "
        
        
        // 身份证
        let idPattern = "(\\d{17}|\\d{14})(\\d|[xX])"
        
        // 电话号码：eg：021-68686868  0511-6868686；
        let phonePattern = "(\\d{3,4}-)\\d{7,8}"
        
        // 手机
        let mobilePhonePattern = "1\\d{10}"
        
        // 邮箱
        let emailPattern = "[a-zA-Z0-9]\\w*@[a-zA-Z0-9]+\\.[a-zA-Z]{2,4}"
        
        
        // 使用 String 的方法 range(of: options: range: locale) 做正则查询（第一处）
        // 使用 String 的方法 replacingOccurrences(of: with: options: range) 做正则替换（所有匹配都替换）
        regexSearch2Replace(originStr: ostr, replaceStr: "====== 身份证 ======", pattern: idPattern);
        regexSearch2Replace(originStr: ostr, replaceStr: "====== 电话号码 ======", pattern: phonePattern);
        regexSearch2Replace(originStr: ostr, replaceStr: "====== 手机 ======", pattern: mobilePhonePattern);
        regexSearch2Replace(originStr: ostr, replaceStr: "====== 邮箱 ======", pattern: emailPattern);
/*
输出:

regexSearch2Replace, find pattern (\d{17}|\d{14})(\d|[xX]) --> find 511122198812068932
regexSearch2Replace, (\d{17}|\d{14})(\d|[xX]) --> ====== 身份证 ====== :
百科熊猫词条  https://baike.baidu.com/item/%E5%A4%A7%E7%86%8A%E7%8C%AB/34935?fromtitle=%E7%86%8A%E7%8C%AB&fromid=162918&fr=aladdin  panda@163.com 大熊猫（学名：Ailuropoda melanoleuca）：属于食肉目、熊科、大熊猫亚科和大熊猫属唯一的哺乳动物，头躯长1.2-1.8米，尾长10-12厘米。体重80-120千克，最重可达180千克，体色为黑白两色，它有着圆圆的脸颊，大大的黑眼圈，胖嘟嘟的身体，标志性的内八字的行走方式，也有解剖刀般锋利的爪子。是世界上最可爱的动物之一。  panda@gmail.com  com.panda@gmail (010)88886666 ，或 022-22334455，或 02912345678 ====== 身份证 ====== ====== 身份证 ====== 18660000062 17000000026
regexSearch2Replace, find pattern (\d{3,4}-)\d{7,8} --> find 022-22334455
regexSearch2Replace, (\d{3,4}-)\d{7,8} --> ====== 电话号码 ====== :
百科熊猫词条  https://baike.baidu.com/item/%E5%A4%A7%E7%86%8A%E7%8C%AB/34935?fromtitle=%E7%86%8A%E7%8C%AB&fromid=162918&fr=aladdin  panda@163.com 大熊猫（学名：Ailuropoda melanoleuca）：属于食肉目、熊科、大熊猫亚科和大熊猫属唯一的哺乳动物，头躯长1.2-1.8米，尾长10-12厘米。体重80-120千克，最重可达180千克，体色为黑白两色，它有着圆圆的脸颊，大大的黑眼圈，胖嘟嘟的身体，标志性的内八字的行走方式，也有解剖刀般锋利的爪子。是世界上最可爱的动物之一。  panda@gmail.com  com.panda@gmail (010)88886666 ，或 ====== 电话号码 ======，或 02912345678 511122198812068932 41112219881206893X 18660000062 17000000026
regexSearch2Replace, find pattern 1\d{10} --> find 11122198812
regexSearch2Replace, 1\d{10} --> ====== 手机 ====== :
百科熊猫词条  https://baike.baidu.com/item/%E5%A4%A7%E7%86%8A%E7%8C%AB/34935?fromtitle=%E7%86%8A%E7%8C%AB&fromid=162918&fr=aladdin  panda@163.com 大熊猫（学名：Ailuropoda melanoleuca）：属于食肉目、熊科、大熊猫亚科和大熊猫属唯一的哺乳动物，头躯长1.2-1.8米，尾长10-12厘米。体重80-120千克，最重可达180千克，体色为黑白两色，它有着圆圆的脸颊，大大的黑眼圈，胖嘟嘟的身体，标志性的内八字的行走方式，也有解剖刀般锋利的爪子。是世界上最可爱的动物之一。  panda@gmail.com  com.panda@gmail (010)88886666 ，或 022-22334455，或 02912345678 5====== 手机 ======068932 4====== 手机 ======06893X ====== 手机 ====== ====== 手机 ======
regexSearch2Replace, find pattern [a-zA-Z0-9]\w*@[a-zA-Z0-9]+\.[a-zA-Z]{2,4} --> find panda@163.com
regexSearch2Replace, [a-zA-Z0-9]\w*@[a-zA-Z0-9]+\.[a-zA-Z]{2,4} --> ====== 邮箱 ====== :
百科熊猫词条  https://baike.baidu.com/item/%E5%A4%A7%E7%86%8A%E7%8C%AB/34935?fromtitle=%E7%86%8A%E7%8C%AB&fromid=162918&fr=aladdin  ====== 邮箱 ====== 大熊猫（学名：Ailuropoda melanoleuca）：属于食肉目、熊科、大熊猫亚科和大熊猫属唯一的哺乳动物，头躯长1.2-1.8米，尾长10-12厘米。体重80-120千克，最重可达180千克，体色为黑白两色，它有着圆圆的脸颊，大大的黑眼圈，胖嘟嘟的身体，标志性的内八字的行走方式，也有解剖刀般锋利的爪子。是世界上最可爱的动物之一。  ====== 邮箱 ======  com.panda@gmail (010)88886666 ，或 022-22334455，或 02912345678 511122198812068932 41112219881206893X 18660000062 17000000026
*/
        
        
        
        regexSearchByRegularExpression(originStr: ostr, replaceStr: "====== 身份证 ======", pattern: idPattern);
        regexSearchByRegularExpression(originStr: ostr, replaceStr: "====== 电话号码 ======", pattern: phonePattern);
        regexSearchByRegularExpression(originStr: ostr, replaceStr: "====== 手机 ======", pattern: mobilePhonePattern);
        regexSearchByRegularExpression(originStr: ostr, replaceStr: "====== 邮箱 ======", pattern: emailPattern);
/*
输出:
 regexSearchByRegularExpression, pattern format done : (\d{17}|\d{14})(\d|[xX])
     match count:2
     firstMatch:<NSSimpleRegularExpressionCheckingResult: 0x600003d5b440>{389, 18}{<NSRegularExpression: 0x600002635620> (\d{17}|\d{14})(\d|[xX]) 0x1}
     allMatch.count:2
         forloop: 0 <NSSimpleRegularExpressionCheckingResult: 0x600003d5b4c0>{389, 18}{<NSRegularExpression: 0x600002635620> (\d{17}|\d{14})(\d|[xX]) 0x1}
         forloop: 1 <NSSimpleRegularExpressionCheckingResult: 0x600003d5b500>{408, 18}{<NSRegularExpression: 0x600002635620> (\d{17}|\d{14})(\d|[xX]) 0x1}
         enumerate block: NSMatchingFlags(rawValue: 0) <NSSimpleRegularExpressionCheckingResult: 0x600003d5b680>{389, 18}{<NSRegularExpression: 0x600002635620> (\d{17}|\d{14})(\d|[xX]) 0x1}
         enumerate block: NSMatchingFlags(rawValue: 0) <NSSimpleRegularExpressionCheckingResult: 0x600003d5b680>{408, 18}{<NSRegularExpression: 0x600002635620> (\d{17}|\d{14})(\d|[xX]) 0x1}
     stringByReplacingMatches --> rpstr : 百科熊猫词条  https://baike.baidu.com/item/%E5%A4%A7%E7%86%8A%E7%8C%AB/34935?fromtitle=%E7%86%8A%E7%8C%AB&fromid=162918&fr=aladdin  panda@163.com 大熊猫（学名：Ailuropoda melanoleuca）：属于食肉目、熊科、大熊猫亚科和大熊猫属唯一的哺乳动物，头躯长1.2-1.8米，尾长10-12厘米。体重80-120千克，最重可达180千克，体色为黑白两色，它有着圆圆的脸颊，大大的黑眼圈，胖嘟嘟的身体，标志性的内八字的行走方式，也有解剖刀般锋利的爪子。是世界上最可爱的动物之一。  panda@gmail.com  com.panda@gmail (010)88886666 ，或 022-22334455，或 02912345678 ====== 身份证 ====== ====== 身份证 ====== 18660000062 17000000026
     replaceMatches(NSMutableString) --> rpCount : 2
     replaceMatches(NSMutableString) --> mostr : 百科熊猫词条  https://baike.baidu.com/item/%E5%A4%A7%E7%86%8A%E7%8C%AB/34935?fromtitle=%E7%86%8A%E7%8C%AB&fromid=162918&fr=aladdin  panda@163.com 大熊猫（学名：Ailuropoda melanoleuca）：属于食肉目、熊科、大熊猫亚科和大熊猫属唯一的哺乳动物，头躯长1.2-1.8米，尾长10-12厘米。体重80-120千克，最重可达180千克，体色为黑白两色，它有着圆圆的脸颊，大大的黑眼圈，胖嘟嘟的身体，标志性的内八字的行走方式，也有解剖刀般锋利的爪子。是世界上最可爱的动物之一。  panda@gmail.com  com.panda@gmail (010)88886666 ，或 022-22334455，或 02912345678 ====== 身份证 ====== ====== 身份证 ====== 18660000062 17000000026
 regexSearchByRegularExpression, pattern format done : (\d{3,4}-)\d{7,8}
     match count:1
     firstMatch:<NSSimpleRegularExpressionCheckingResult: 0x600003d5b980>{362, 12}{<NSRegularExpression: 0x600002635860> (\d{3,4}-)\d{7,8} 0x1}
     allMatch.count:1
         forloop: 0 <NSSimpleRegularExpressionCheckingResult: 0x600003d5b9c0>{362, 12}{<NSRegularExpression: 0x600002635860> (\d{3,4}-)\d{7,8} 0x1}
         enumerate block: NSMatchingFlags(rawValue: 0) <NSSimpleRegularExpressionCheckingResult: 0x600003d5b900>{362, 12}{<NSRegularExpression: 0x600002635860> (\d{3,4}-)\d{7,8} 0x1}
     stringByReplacingMatches --> rpstr : 百科熊猫词条  https://baike.baidu.com/item/%E5%A4%A7%E7%86%8A%E7%8C%AB/34935?fromtitle=%E7%86%8A%E7%8C%AB&fromid=162918&fr=aladdin  panda@163.com 大熊猫（学名：Ailuropoda melanoleuca）：属于食肉目、熊科、大熊猫亚科和大熊猫属唯一的哺乳动物，头躯长1.2-1.8米，尾长10-12厘米。体重80-120千克，最重可达180千克，体色为黑白两色，它有着圆圆的脸颊，大大的黑眼圈，胖嘟嘟的身体，标志性的内八字的行走方式，也有解剖刀般锋利的爪子。是世界上最可爱的动物之一。  panda@gmail.com  com.panda@gmail (010)88886666 ，或 ====== 电话号码 ======，或 02912345678 511122198812068932 41112219881206893X 18660000062 17000000026
     replaceMatches(NSMutableString) --> rpCount : 1
     replaceMatches(NSMutableString) --> mostr : 百科熊猫词条  https://baike.baidu.com/item/%E5%A4%A7%E7%86%8A%E7%8C%AB/34935?fromtitle=%E7%86%8A%E7%8C%AB&fromid=162918&fr=aladdin  panda@163.com 大熊猫（学名：Ailuropoda melanoleuca）：属于食肉目、熊科、大熊猫亚科和大熊猫属唯一的哺乳动物，头躯长1.2-1.8米，尾长10-12厘米。体重80-120千克，最重可达180千克，体色为黑白两色，它有着圆圆的脸颊，大大的黑眼圈，胖嘟嘟的身体，标志性的内八字的行走方式，也有解剖刀般锋利的爪子。是世界上最可爱的动物之一。  panda@gmail.com  com.panda@gmail (010)88886666 ，或 ====== 电话号码 ======，或 02912345678 511122198812068932 41112219881206893X 18660000062 17000000026
 regexSearchByRegularExpression, pattern format done : 1\d{10}
     match count:4
     firstMatch:<NSSimpleRegularExpressionCheckingResult: 0x600003d5bc00>{390, 11}{<NSRegularExpression: 0x600002635b90> 1\d{10} 0x1}
     allMatch.count:4
         forloop: 0 <NSSimpleRegularExpressionCheckingResult: 0x600003d5bb40>{390, 11}{<NSRegularExpression: 0x600002635b90> 1\d{10} 0x1}
         forloop: 1 <NSSimpleRegularExpressionCheckingResult: 0x600003d5bc40>{409, 11}{<NSRegularExpression: 0x600002635b90> 1\d{10} 0x1}
         forloop: 2 <NSSimpleRegularExpressionCheckingResult: 0x600003d5bcc0>{427, 11}{<NSRegularExpression: 0x600002635b90> 1\d{10} 0x1}
         forloop: 3 <NSSimpleRegularExpressionCheckingResult: 0x600003d5bd00>{439, 11}{<NSRegularExpression: 0x600002635b90> 1\d{10} 0x1}
         enumerate block: NSMatchingFlags(rawValue: 0) <NSSimpleRegularExpressionCheckingResult: 0x600003d5bd40>{390, 11}{<NSRegularExpression: 0x600002635b90> 1\d{10} 0x1}
         enumerate block: NSMatchingFlags(rawValue: 0) <NSSimpleRegularExpressionCheckingResult: 0x600003d5bd40>{409, 11}{<NSRegularExpression: 0x600002635b90> 1\d{10} 0x1}
         enumerate block: NSMatchingFlags(rawValue: 0) <NSSimpleRegularExpressionCheckingResult: 0x600003d5bd40>{427, 11}{<NSRegularExpression: 0x600002635b90> 1\d{10} 0x1}
         enumerate block: NSMatchingFlags(rawValue: 0) <NSSimpleRegularExpressionCheckingResult: 0x600003d5bd40>{439, 11}{<NSRegularExpression: 0x600002635b90> 1\d{10} 0x1}
     stringByReplacingMatches --> rpstr : 百科熊猫词条  https://baike.baidu.com/item/%E5%A4%A7%E7%86%8A%E7%8C%AB/34935?fromtitle=%E7%86%8A%E7%8C%AB&fromid=162918&fr=aladdin  panda@163.com 大熊猫（学名：Ailuropoda melanoleuca）：属于食肉目、熊科、大熊猫亚科和大熊猫属唯一的哺乳动物，头躯长1.2-1.8米，尾长10-12厘米。体重80-120千克，最重可达180千克，体色为黑白两色，它有着圆圆的脸颊，大大的黑眼圈，胖嘟嘟的身体，标志性的内八字的行走方式，也有解剖刀般锋利的爪子。是世界上最可爱的动物之一。  panda@gmail.com  com.panda@gmail (010)88886666 ，或 022-22334455，或 02912345678 5====== 手机 ======068932 4====== 手机 ======06893X ====== 手机 ====== ====== 手机 ======
     replaceMatches(NSMutableString) --> rpCount : 4
     replaceMatches(NSMutableString) --> mostr : 百科熊猫词条  https://baike.baidu.com/item/%E5%A4%A7%E7%86%8A%E7%8C%AB/34935?fromtitle=%E7%86%8A%E7%8C%AB&fromid=162918&fr=aladdin  panda@163.com 大熊猫（学名：Ailuropoda melanoleuca）：属于食肉目、熊科、大熊猫亚科和大熊猫属唯一的哺乳动物，头躯长1.2-1.8米，尾长10-12厘米。体重80-120千克，最重可达180千克，体色为黑白两色，它有着圆圆的脸颊，大大的黑眼圈，胖嘟嘟的身体，标志性的内八字的行走方式，也有解剖刀般锋利的爪子。是世界上最可爱的动物之一。  panda@gmail.com  com.panda@gmail (010)88886666 ，或 022-22334455，或 02912345678 5====== 手机 ======068932 4====== 手机 ======06893X ====== 手机 ====== ====== 手机 ======
 regexSearchByRegularExpression, pattern format done : [a-zA-Z0-9]\w*@[a-zA-Z0-9]+\.[a-zA-Z]{2,4}
     match count:2
     firstMatch:<NSSimpleRegularExpressionCheckingResult: 0x600003d38640>{126, 13}{<NSRegularExpression: 0x600002609230> [a-zA-Z0-9]\w*@[a-zA-Z0-9]+\.[a-zA-Z]{2,4} 0x1}
     allMatch.count:2
         forloop: 0 <NSSimpleRegularExpressionCheckingResult: 0x600003d38440>{126, 13}{<NSRegularExpression: 0x600002609230> [a-zA-Z0-9]\w*@[a-zA-Z0-9]+\.[a-zA-Z]{2,4} 0x1}
         forloop: 1 <NSSimpleRegularExpressionCheckingResult: 0x600003d381c0>{312, 15}{<NSRegularExpression: 0x600002609230> [a-zA-Z0-9]\w*@[a-zA-Z0-9]+\.[a-zA-Z]{2,4} 0x1}
         enumerate block: NSMatchingFlags(rawValue: 0) <NSSimpleRegularExpressionCheckingResult: 0x600003d380c0>{126, 13}{<NSRegularExpression: 0x600002609230> [a-zA-Z0-9]\w*@[a-zA-Z0-9]+\.[a-zA-Z]{2,4} 0x1}
         enumerate block: NSMatchingFlags(rawValue: 0) <NSSimpleRegularExpressionCheckingResult: 0x600003d380c0>{312, 15}{<NSRegularExpression: 0x600002609230> [a-zA-Z0-9]\w*@[a-zA-Z0-9]+\.[a-zA-Z]{2,4} 0x1}
     stringByReplacingMatches --> rpstr : 百科熊猫词条  https://baike.baidu.com/item/%E5%A4%A7%E7%86%8A%E7%8C%AB/34935?fromtitle=%E7%86%8A%E7%8C%AB&fromid=162918&fr=aladdin  ====== 邮箱 ====== 大熊猫（学名：Ailuropoda melanoleuca）：属于食肉目、熊科、大熊猫亚科和大熊猫属唯一的哺乳动物，头躯长1.2-1.8米，尾长10-12厘米。体重80-120千克，最重可达180千克，体色为黑白两色，它有着圆圆的脸颊，大大的黑眼圈，胖嘟嘟的身体，标志性的内八字的行走方式，也有解剖刀般锋利的爪子。是世界上最可爱的动物之一。  ====== 邮箱 ======  com.panda@gmail (010)88886666 ，或 022-22334455，或 02912345678 511122198812068932 41112219881206893X 18660000062 17000000026
     replaceMatches(NSMutableString) --> rpCount : 2
     replaceMatches(NSMutableString) --> mostr : 百科熊猫词条  https://baike.baidu.com/item/%E5%A4%A7%E7%86%8A%E7%8C%AB/34935?fromtitle=%E7%86%8A%E7%8C%AB&fromid=162918&fr=aladdin  ====== 邮箱 ====== 大熊猫（学名：Ailuropoda melanoleuca）：属于食肉目、熊科、大熊猫亚科和大熊猫属唯一的哺乳动物，头躯长1.2-1.8米，尾长10-12厘米。体重80-120千克，最重可达180千克，体色为黑白两色，它有着圆圆的脸颊，大大的黑眼圈，胖嘟嘟的身体，标志性的内八字的行走方式，也有解剖刀般锋利的爪子。是世界上最可爱的动物之一。  ====== 邮箱 ======  com.panda@gmail (010)88886666 ，或 022-22334455，或 02912345678 511122198812068932 41112219881206893X 18660000062 17000000026
*/
        
        
        // 使用 NSPredicate 判别 ostr 是否符合 pattern
        regexPredicate(ostr:"51112219881206893X", pattern: idPattern);
        regexPredicate(ostr:"022-22334455", pattern: phonePattern);
        regexPredicate(ostr:"17000000026", pattern: emailPattern);
/*
输出:

NSPredicate, 51112219881206893X match idPattern : (\d{17}|\d{14})(\d|[xX])
NSPredicate, 022-22334455 match idPattern : (\d{3,4}-)\d{7,8}
NSPredicate, 17000000026 not match idPattern : [a-zA-Z0-9]\w*@[a-zA-Z0-9]+\.[a-zA-Z]{2,4}
*/
    }
    
    // String 原生方法，双端trim
    class func stringTrimed(str4Trim:String) -> String {
        if(str4Trim.count == 0) {
            return "";
        }
        
        return str4Trim.trimmingCharacters(in: .whitespacesAndNewlines)
    }
    
    // String 原生方法 正则替换，左trim
    class func stringLeftTrimed(str4Trim:String) -> String {
        if(str4Trim.count == 0) {
            return "";
        }
        
        let pattern = "^(\\s)*";
        let rpstr = str4Trim.replacingOccurrences(of: pattern,
                                       with: "",
                                       options: .regularExpression,
                                       range: str4Trim.startIndex ..< str4Trim.endIndex)
        return rpstr;
    }
    
    // String 原生方法 正则替换，右trim
    class func stringRightTrimed(str4Trim:String) -> String {
        if(str4Trim.count == 0) {
            return "";
        }
        
        let pattern = "(\\s)*$";
        let rpstr = str4Trim.replacingOccurrences(of: pattern,
                                       with: "",
                                       options: .regularExpression,
                                       range: str4Trim.startIndex ..< str4Trim.endIndex)
        return rpstr;
    }

    class func stringTrim() {
        let ostr = " \t 2sapce+1tab 山外青山楼外楼 3space   ";
        let trimstr =       stringTrimed(str4Trim:ostr)
        let leftTrimstr =   stringLeftTrimed(str4Trim:ostr)
        let rightTrimstr =  stringRightTrimed(str4Trim:ostr)
        
        print("stringTrim\nostr        :|\(ostr)|\ntrimstr     :|\(trimstr)|\nleftTrimstr :|\(leftTrimstr)|\nrightTrimstr:|\(rightTrimstr)|");

/*
输出：

ostr        :|      2sapce+1tab 山外青山楼外楼 3space   |
trimstr     :|2sapce+1tab 山外青山楼外楼 3space|
leftTrimstr :|2sapce+1tab 山外青山楼外楼 3space   |
rightTrimstr:|      2sapce+1tab 山外青山楼外楼 3space|
*/
    }
    
    class func demoLogic() {
        
        stringFromToArray()
        
        stringJoin()
        
        subStringSearch()
        
        regexSearch()
        
        stringTrim()
        
        stringFormat()
        
        stringFromToDate()
        
        
    }
}
